#pragma once
#include <iostream>
using namespace std;
#include <unistd.h>
#include <string>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <functional>
#include "log.hpp"
#include <signal.h>
#include <sys/select.h>

using namespace std;

namespace Server
{
    class tcpServer
    {
        typedef function<void(int)> func_t;

    public:
        tcpServer(const func_t &callback, const uint16_t &port = 8080) : _callback(callback), listen_sock(-1), _port(port)
        {
        }

        void initServer()
        {
            // 1:开启套接字
            listen_sock = socket(AF_INET, SOCK_STREAM, 0);
            if (listen_sock < 0)
            {
                logMessage(4, "socket errno");
                exit(1);
            }
            logMessage(1, "socket success");

            // 1.1：设置端口复用
            int opt = 1;
            setsockopt(listen_sock, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt));

            // 2:开始bind
            sockaddr_in local;
            local.sin_family = AF_INET;
            local.sin_port = htons(_port);
            local.sin_addr.s_addr = INADDR_ANY;

            int n = bind(listen_sock, (sockaddr *)&local, sizeof(local));
            if (n < 0)
            {
                logMessage(4, "bind errno");
                exit(1);
            }
            logMessage(1, "bind success");

            // 3:设置为监听
            int ret = listen(listen_sock, 5);
            if (ret < 0)
            {
                logMessage(3, "listen fail");
            }
            logMessage(1, "listen success");
        }
        void start()
        {
            // 2：改为select版本

            // 1:初始化要检测的集合
            fd_set reads, tmp;
            FD_ZERO(&reads);
            FD_SET(listen_sock, &reads);

            int nfds = listen_sock;
            // int sock = 0;
            while (1)
            {
                sockaddr_in peer;
                socklen_t len = sizeof(peer);

                tmp = reads;
                int num = select(nfds + 1, &tmp, nullptr, nullptr, nullptr);
                printf("num = %d\n", num);
                for (int i = 0; i <= nfds; i++)
                {
                    if (i == listen_sock && FD_ISSET(listen_sock, &tmp))
                    {
                        // 建立新连接：
                        int sock = accept(listen_sock, (sockaddr *)&peer, &len);
                        if (sock < 0)
                        {
                            logMessage(3, "accept fail");
                            continue;
                        }
                        logMessage(1, "accept success");

                        FD_SET(sock, &reads);
                        // 要更新nfds
                        nfds = nfds < sock ? sock : nfds;
                    }
                    else
                    {
                        // 通信
                        if (FD_ISSET(i, &tmp))
                        {
                            // _callback(sock);
                            char buffer[1024];
                            memset(buffer, 0, sizeof(buffer));
                            int len = read(i, buffer, sizeof(buffer) - 1);
                            if (len > 0)
                            {
                                buffer[len] = 0;
                                cout << buffer << endl;
                                write(i, buffer, sizeof(buffer));
                            }
                            else if (len == 0)
                            {
                                printf("客户端断开连接。。\n");
                                FD_CLR(i, &reads);
                                close(i);
                            }
                            else
                            {
                                break;
                            }
                        }
                    }
                }
            }

            // signal(17,SIG_IGN);

            // while (1)
            // {
            //     // 4:accpet客户端的请求
            //     sockaddr_in peer;
            //     // memset(&peer, 0, sizeof(peer));
            //     socklen_t len = sizeof(peer);
            //     int sock = accept(listen_sock, (sockaddr *)&peer, &len);
            //     if (sock < 0)
            //     {
            //         logMessage(4, "accept fail,wait");
            //         continue;
            //     }
            //     logMessage(1, "accept success");
            //     cout << "sock:" << sock << endl;
            //     // 开始处理业务逻辑

            //     //2：多进程版
            //     pid_t id = fork();
            //     if(id == 0){
            //         close(listen_sock);
            //         _callback(sock);
            //         close(sock);
            //     }
            //     //主进程只负责接收
            //     close(sock);

            // }
        }

        ~tcpServer()
        {
        }

    private:
        int listen_sock;
        uint16_t _port;

        func_t _callback; // 回调函数，用于处理服务器对客户端发过来的数据
    };

}
